from PIL import Image
import pdb

def plus(str):
    # 返回指定长度的字符串，原字符串右对齐，前面填充0。
    return str.zfill(8)


def getCode(img):
    str = ""
    # 创建一个名为'str'的空字符串，用于存储编码后的像素数据
    # 获取到水印的宽和高进行遍历
    # img.size[0]和img.size[1]用来获取图像的宽度和高度。这种方式的使用是基于某些图像处理库（PIL）的约定
    for i in range(img.size[0]):
        for j in range(img.size[1]):

            # 获取水印的每个像素值
            gray_value = img.getpixel((i, j))

            # pdb.set_trace()
            # print(rgb)

            # 将像素值转为二进制后保存
            str = str + plus(bin(gray_value).replace('0b', ''))

            # .replace('0b', ''):这部分代码用于去除二进制字符串的开头的 '0b'，以使二进制字符串更加干净。例如，'0b11111111' 将被转换为 '11111111'。
            # print(plus(bin(rgb[0]).replace('0b', ''))+"\n")
            # print(plus(bin(rgb[1]).replace('0b', '')) + "\n")
            # print(plus(bin(rgb[2]).replace('0b', '')) + "\n")
    # print(str)
    return str


def encry(img, code):

    # 计数器
    count = 0

    # 二进制像素值的长度，可以认为要写入图像的文本长度，提取（解密）时也需要此变量
    codeLen = len(code)

    # pdb.set_trace()
    # print(codeLen)


    # 获取到图像的宽、高进行遍历
    for i in range(img.size[0]):
        for j in range(img.size[1]):
            # 获取到图片的每个像素值
            gray_value = img.getpixel((i, j))

            # 如果计数器等于长度，代表水印写入完成
            if count == codeLen:
                break

            """
            下面的是像素值替换，通过取模2得到最后一位像素值（0或1），
            然后减去最后一位像素值，在将code的值添加过来
            """
            new_gray_value = (gray_value - gray_value % 2) + int(code[count])

            count += 1
            if count == codeLen:
                img.putpixel((i, j), new_gray_value)
                break
            # 更新图像像素值
            img.putpixel((i, j), new_gray_value)
    img.save("加密图片1.bmp")
    img.show()




# 获取图像对象
img1 = Image.open('原始图片.bmp')
img2 = Image.open('水印图片.bmp')

# 将图像转换为灰度模式
gray_img1 = img1.convert('L')
gray_img2 = img2.convert('L')

# 将水印的像素值转为文本
code = getCode(gray_img2)

# 将水印写入图像
encry(gray_img1, code)

